#ifndef cathlibcpp_sstream_H
#define cathlibcpp_sstream_H

// File:       sstream.h
// Author:     (c) Miles Sabin, 1997
// Purpose:    approximation to ANSI C++ sstream header


#ifndef cathlibcpp_config_H
#include "config.h"
#endif

#ifndef cathlibcpp_istream_H
#include "istream.h"
#endif

#ifndef cathlibcpp_newcasts_H
#include "newcasts.h"
#endif

#ifndef cathlibcpp_ostream_H
#include "ostream.h"
#endif

#ifndef cathlibcpp_streambuf_H
#include "streambuf.h"
#endif

#ifndef cathlibcpp_stream_H
#include "stream.h"
#endif

#ifndef cathlibcpp_string_H
#include "string.h"
#endif


class basic_stringbuf_char;
typedef basic_stringbuf_char stringbuf;

class basic_istringstream_char;
typedef basic_istringstream_char istringstream;

class basic_ostringstream_char;
typedef basic_ostringstream_char ostringstream;

class basic_stringstream_char;
typedef basic_stringstream_char stringstream;


class basic_stringbuf_char : public basic_streambuf_char
{
  public:

    // types
    typedef char_traits_char traits;

    // constructors
    basic_stringbuf_char(ios_base::openmode which = ios_base::in|ios_base::out);
    basic_stringbuf_char(basic_string_char const& str, ios_base::openmode which = ios_base::in|ios_base::out);
    ~basic_stringbuf_char();

    // get and set
    basic_string_char str() const;
    void str(basic_string_char const& s);

  protected:

    virtual int underflow();
    virtual int pbackfail(int c = traits::eof());
    virtual int overflow(int c = traits::eof());

    virtual int seekoff(int off, ios_base::seekdir way, ios_base::openmode which = ios_base::in|ios_base::out);
    virtual int seekpos(int sp, ios_base::openmode which = ios_base::in|ios_base::out);

  private:

    void set_pointers();

    ios_base::openmode mode_;
    basic_string_char buffer_;
    int min_sequence_length_;
};


class basic_istringstream_char : public basic_istream_char
{
  public:

    // types
    typedef char_traits_char traits;

    // constructors
    basic_istringstream_char(ios_base::openmode which = ios_base::in);
    basic_istringstream_char(basic_string_char const& str, ios_base::openmode which = ios_base::in);

    // accessors
    basic_stringbuf_char* rdbuf() const;

    basic_string_char str() const;

    // mutators
    void str(basic_string_char const& s);

  private:

    basic_stringbuf_char sb_;
};


class basic_ostringstream_char : public basic_ostream_char
{
  public:

    // types
    typedef char_traits_char traits;

    // constructors
    basic_ostringstream_char(ios_base::openmode which = ios_base::out);
    basic_ostringstream_char(basic_string_char const& str, ios_base::openmode which = ios_base::out);

    // accessors
    basic_stringbuf_char* rdbuf() const;

    basic_string_char str() const;

    // mutators
    void str(basic_string_char const& s);

  private:

    basic_stringbuf_char sb_;
};


class basic_stringstream_char : public basic_iostream_char
{
  public:

    // types
    typedef char_traits_char traits;

    // constructors
    basic_stringstream_char(ios_base::openmode which = ios_base::out|ios_base::in);
    basic_stringstream_char(basic_string_char const& str, ios_base::openmode which = ios_base::out|ios_base::in);

    // accessors
    basic_stringbuf_char* rdbuf() const;

    basic_string_char str() const;

    // mutators
    void str(basic_string_char const& s);

  private:

    basic_stringbuf_char sb_;
};


// Implementation of basic_istringstream_char

inline basic_istringstream_char::basic_istringstream_char(ios_base::openmode which)
  : basic_istream_char(&sb_),
    sb_(which|ios_base::in)
  {}

inline basic_istringstream_char::basic_istringstream_char(basic_string_char const& str, ios_base::openmode which)
  : basic_istream_char(&sb_),
    sb_(str, which|ios_base::in)
  {}

inline basic_stringbuf_char* basic_istringstream_char::rdbuf() const
  { return const_cast(basic_stringbuf_char*, &sb_); }

inline basic_string_char basic_istringstream_char::str() const
  { return sb_.str(); }

inline void basic_istringstream_char::str(basic_string_char const& s)
  { sb_.str(s); }


// Implementation of basic_ostringstream_char

inline basic_ostringstream_char::basic_ostringstream_char(ios_base::openmode which)
  : basic_ostream_char(&sb_),
    sb_(which|ios_base::out)
  {}

inline basic_ostringstream_char::basic_ostringstream_char(basic_string_char const& str, ios_base::openmode which)
  : basic_ostream_char(&sb_),
    sb_(str, which|ios_base::out)
  {}

inline basic_stringbuf_char* basic_ostringstream_char::rdbuf() const
  { return const_cast(basic_stringbuf_char*, &sb_); }

inline basic_string_char basic_ostringstream_char::str() const
  { return sb_.str(); }

inline void basic_ostringstream_char::str(basic_string_char const& s)
  { sb_.str(s); }


// Implementation of basic_stringstream_char

inline basic_stringstream_char::basic_stringstream_char(ios_base::openmode which)
  : basic_iostream_char(&sb_),
    sb_(which)
  {}

inline basic_stringstream_char::basic_stringstream_char(basic_string_char const& str, ios_base::openmode which)
  : basic_iostream_char(&sb_),
    sb_(str, which)
  {}

inline basic_stringbuf_char* basic_stringstream_char::rdbuf() const
  { return const_cast(basic_stringbuf_char*, &sb_); }

inline basic_string_char basic_stringstream_char::str() const
  { return sb_.str(); }

inline void basic_stringstream_char::str(basic_string_char const& s)
  { sb_.str(s); }

#endif
